﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Wordprocessing;

using ProjectBase.Core;

namespace ProjectBase.Tools.Export.Word
{
    public static partial class Ext
    {
        public static DocPart CreateDocPart(this IList<DocPart> list, string name)
        {
            var dp = new DocPart
            {
                DocPartProperties = new DocPartProperties
                {
                    DocPartName = new DocPartName
                    {
                        Val = name.ConvertToEntityPath(),
                    }
                },
            };
            list.Add(dp);
            return dp;
        }

        /// <summary>
        /// Converts the bookmark "entity_innerEntity_property" to 
        /// "entity.innerEntity.property"
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ConvertToEntityPath(this string name)
        {
            // inside the string "_0_"
            var strict = new Regex(Const.RegExprContainsDigit);
            if (strict.IsMatch(name))
            {
                name = strict.Replace(name, Const.UnderScore);
            }

            // ends as the string: "_0"
            strict = new Regex(Const.RegExprEndsWithDigit);
            if (strict.IsMatch(name))
            {
                name = name.Substring(0, name.Length - 2);
            }

            // replace "_" with "."
            return name.Replace(Const.UnderScore, Const.Dot);
        }

        /// <summary>
        /// DocPart is removed, all its children are (re)placed to the current DocPart posisiton.
        /// </summary>
        /// <param name="part"></param>
        public static void RestoreElements(this DocPart part)
        {
            if (part.IsNull() || part.Parent.IsNull())
            {
                return;
            }

            foreach (var element in part.Elements().ToList())
            {
                if (element is DocPartProperties)
                {
                    continue;
                }
                element.Remove();
                part.InsertBeforeSelf(element);
            }

            part.Remove();
        }

        /// <summary>
        /// For block DocParts: returns inner Elements with at least one Run/Text element.
        /// for inlines DocParts: new Run/Text element(s) are returned.
        /// </summary>
        /// <param name="part"></param>
        /// <param name="text">text to be inserted in te first Run/Text element</param>
        /// <param name="isLast"></param>
        /// <returns></returns>
        public static DocPart CreateTextElement(this DocPart part, string text, bool isLast)
        {
            var result = part.CloneNode(true) as DocPart;

            // block
            if (part.Descendants<Paragraph>().Count() > 0)
            {
                var p = result.Descendants<Paragraph>().First();
                var t = p.Descendants<Text>();
                if (t.Count() > 0)
                {
                    foreach (var txt in t)
                    {
                        txt.Text = string.Empty; // clear all existing Texts
                    }
                    t.First().Text = text;
                }
                else
                {
                    if (p.Descendants<Run>().Count() > 0) // change the first or
                    {
                        p.Descendants<Run>().First().Append(new Text(text));
                    }
                    else // create new 
                    {
                        p.Append(new Run(new Text(text)));
                    }
                }
                return result;
            }

            // inline
            result = new DocPart(new Run(new Text(text)));
            if (!isLast)
            {
                result.Append(new Run(new Text(Const.Comma + Const.Space) { Space = SpaceProcessingModeValues.Preserve }));
            }

            return result;
        }

        /// <summary>
        /// Gets the name of the DocPart
        /// (DocPart.DocPartProperties.DocPartName.Val.Value) 
        /// and removes the provided prefixes (e.g. States.Name results in Name)
        /// </summary>
        /// <param name="dp"></param>
        /// <param name="prefixes"></param>
        /// <returns></returns>
        public static string Name(this DocPart dp, params string[] prefixes)
        {
            var name = dp.DocPartProperties.DocPartName.Val.Value;
            if (prefixes.IsNotEmpty())
            {
                foreach (var prefix in prefixes)
                {
                    if (name.StartsWith(prefix))
                    {
                        name = name.Substring(prefix.Length).TrimStart('.');
                    }
                }
            }
            return name;
        }
    }
}